﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using X.Core.Bases;
using X.Core.Utils;

namespace X.Core.Models
{
    public class BitDataModel : ParameterModelBase
    {
        public BitDataModel() : base()
        {
            IsEnabled = true;
            Address = -1;
            LastOnTime = DateTime.Now;
        }
        public override (int, string) Fill<T>(T source, bool isCheckType = true, IEnumerable<string> ignorePropList = null)
        {
            var bit = source as BitDataModel;
            base.Fill(bit);
            IsIgnored = bit.IsIgnored;
            Group = bit.Group;
            GroupSub = bit.GroupSub;
            Address = bit.Address;
            BPV = bit.BPV;
            return (0,null);
        }
        private bool _pv;
        DateTime _reverseStartTime;
        uint _reverseStartTick;
        DateTime _delayReverseRecordTime;
        bool _reversetStatus;
        bool _delayReversetStatus;
        int _address;
        int _pin = 0;
        public bool IsReadOnly { get; set; } = false;
        public int Level { get; set; }
        public bool IsStatic { get; set; }
        public double ReverseTime { get; set; }
        public bool CanReverse { get; set; }
        public bool CanDelayReverse { get; set; }
        public bool CanRepeat { get; set; }
        public bool IsIgnored { get; set; }
        public int MaxOnTime { get; set; }
        public DateTime LastOnTime { get; set; }
        public int Address
        {
            get => _address; set
            {
                if (_address == value) return; _address = value;
                if (value >= 0) _pin = 1 << value; else _pin = 0; RaisePropertyChanged(nameof(Address));
            }
        }
        [JsonIgnore]
        public int Pin => _pin;
        public bool IsVirtual => Address < 0;
        public bool BPV
        {
            get => _pv; set
            {
                if (_pv != value)
                {
                    if (value)
                    {
                        LastOnTime = DateTime.Now;
                    }
                    _pv = value;
                    IsChanged = true;
                    RaisePropertyChanged(nameof(BPV));
                }
            }
        }
        [JsonIgnore]
        public virtual BitDataModel Output { get; set; }
        [JsonIgnore]
        public virtual BitDataModel Upper { get; set; }
        [JsonIgnore]
        public virtual BitDataModel Lower { get; set; }
        [JsonIgnore]
        public DateTime ReverseStart => _reverseStartTime;
        public void SetBit()
        {
            BPV = true;
        }
        public void Reset()
        {
            BPV = false;
            _reverseStartTime = DateTime.Now;
            CanRepeat = false;
            CanReverse = false;
        }
        public void SetDelayReverse(bool bValue, double reverseTime = 500, bool canRepeat = false, int delayTime = 500)
        {
            _delayReversetStatus = bValue;
            _delayReverseRecordTime = DateTime.Now;
            _reverseStartTime = _delayReverseRecordTime.AddMilliseconds(delayTime);
            ReverseTime = reverseTime;
            CanReverse = true;
            CanDelayReverse = true;
            CanRepeat = canRepeat;
        }
        public void SetReverse(bool bValue, double reverseTime = 500, bool canRepeat = false)
        {
            BPV = bValue;
            _reversetStatus = !bValue;
            _reverseStartTime = DateTime.Now;
            _reverseStartTick = Util.GetTickCount();
            ReverseTime = reverseTime;
            CanReverse = true;
            CanRepeat = canRepeat;
        }
        public void Reverse()
        {
            if (MaxOnTime > 0)
            {
                if ((DateTime.Now - LastOnTime).TotalMilliseconds > MaxOnTime)
                {
                    BPV = false;
                    return;
                }
            }
            if (CanReverse == false && CanDelayReverse == false) return;
            var t = DateTime.Now;
            if (CanDelayReverse)
            {
                //if(DateTime.Compare(_delayReverseRecordTime,_reverseStartTime) <= 0)
                if (DateTime.Compare(t, _reverseStartTime) >= 0)
                {
                    SetReverse(_delayReversetStatus, ReverseTime, false);
                    CanDelayReverse = false;
                }
            }

            //if ((t - _reverseStartTime).TotalMilliseconds >= ReverseTime)
            if (Util.GetDuration(_reverseStartTick) >= ReverseTime)
            {
                BPV = _reversetStatus;
                if (CanRepeat)
                {
                    _reversetStatus = !_reversetStatus;
                    CanReverse = true;
                    _reverseStartTime = DateTime.Now;
                    _reverseStartTick = Util.GetTickCount();
                }
                else
                {
                    CanReverse = false;
                }
            }
        }

        public override string ToString()
        {
            return $"{Name} {BPV}";
        }

    }
}
